/*
 * ACM_FEM_SeparateCG_Controller.h
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#ifndef ACM_FEM_SEPARATECG_CONTROLLER_H_
#define ACM_FEM_SEPARATECG_CONTROLLER_H_

#include <string>
#include <iostream>
#include "ACM_FEM/OptimizationObject.h"
#include "include/base/cell_models/ACM/ActiveCableModel.h"
#include "ACM_FEM/SeparatedCGOptimizer.h"
#include "include/base/utility/FieldInterpolation2D.h"
#include "ACM_FEM/DataSimulator.h"

using namespace std;

class ACM_FEM_SeparateCG_Controller {
public:
	ACM_FEM_SeparateCG_Controller(string parameter_file){
		OptimizationObject* opti_object = new OptimizationObject(parameter_file);
		system(("mkdir " + opti_object->get_project_folder()).c_str());
		opti_object->save_parameters(opti_object->get_project_folder() + "/parameter_settings.log");

		if(opti_object->is_simulated_data_enabled()){
			DataSimulator ds(opti_object,false);
			ds.write_displacement_file(opti_object->get_project_folder() + "/sim_disp.txt",10000);
			opti_object->set_disp_file(opti_object->get_project_folder() + "/sim_disp.txt");
		}

		//Save experimental displacements in vtk format for visualization
		Point<2> p1(opti_object->get_mesh_point1()(0),opti_object->get_mesh_point1()(1));
		Point<2> p2(opti_object->get_mesh_point2()(0),opti_object->get_mesh_point2()(1));
		FieldInterpolation2D * interpol = new FieldInterpolation2D(p1, p2, opti_object->get_degree_of_refinement(), opti_object->get_disp_file());
		interpol->output(opti_object->get_project_folder() + "/displacements.vtk");

		//Shift mesh to reference (=nondisplaced) state
		if(opti_object->is_preshifting_enabled())
		{
			ActiveCableModel::createShiftedVTK(
										opti_object->get_cell_mesh_file(),
										opti_object->get_project_folder() + "/tmp.vtk",
										interpol);
			opti_object->set_cell_mesh_file(opti_object->get_project_folder() + "/tmp.vtk");
		}


		int dofnr = ActiveCableModel::getFiberList(opti_object->get_cell_mesh_file()).size()+1;
		cout << dofnr << endl;
		cout << "Create ACM" << endl;
		ActiveCableModel * acm = new ActiveCableModel(opti_object->get_cell_mesh_file(),opti_object->get_project_folder(),50.0,vector<double>(dofnr,0));
		cout << "Create FEM" << endl;
		FEMCalc * fem = new FEMCalc(opti_object->get_young_mod(),opti_object->get_poisson_ratio(),opti_object->get_mesh_point1(),
				opti_object->get_mesh_point2(),opti_object->get_degree_of_refinement(),acm->getForceTransmissionShapes());
		cout << "Create L2Comparator with displacement file " << opti_object->get_disp_file() << endl;
		L2Comparator * comp = new L2Comparator(new DataContainer(opti_object->get_disp_file()));
		cout << "Create SeparatedCGOptimizer" << endl;
		Optimizer * opt = new SeparatedCGOptimizer(acm, fem, comp,opti_object->get_project_folder(), 200, opti_object->get_n_threads(), 0.001, 0.001, 10, true);
		cout << "Run Optimizer" << endl;
		opt->run();
	};
};


#endif /* ACM_FEM_SEPARATECG_CONTROLLER_H_ */
